package com.feng.cloud.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.cloud.common.exception.system.ParameterException;
import com.feng.cloud.common.exception.system.SystemStatus;
import com.feng.cloud.system.dto.MenuTree;
import com.feng.cloud.system.dto.RouterMeta;
import com.feng.cloud.system.dto.VueRouter;
import com.feng.cloud.system.entity.Menu;
import com.feng.cloud.system.mapper.MenuMapper;
import com.feng.cloud.system.utils.TreeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @ClassName MenuService
 * @Description TODO
 * @Author Better Feng
 * @Date 2019/12/21 22:29
 * @Version 1.0
 **/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class MenuService extends ServiceImpl<MenuMapper, Menu> {

    public List<VueRouter<Menu>> getUserRouters(String username) {
        List<VueRouter<Menu>> routes = new ArrayList<>();
        List<Menu> menus = this.baseMapper.findUserMenus(username);
        menus.forEach(menu -> {
            VueRouter<Menu> route = new VueRouter<>();
            route.setId(menu.getMenuId().toString());
            route.setParentId(menu.getParentId().toString());
            route.setPath(menu.getPath());
            route.setComponent(menu.getComponent());
            route.setName(menu.getMenuName());
            route.setMeta(new RouterMeta(menu.getMenuName(), menu.getIcon(), true));
            routes.add(route);
        });
        return TreeUtils.buildVueRouter(routes);
    }

    public List<String> findUserPermissions(String username) {
        List<String> list = Collections.emptyList();
        List<String> userPermissions = this.baseMapper.findUserPermissions(username);
        if (!CollectionUtils.isEmpty(userPermissions)) {
            return userPermissions;
        }
        return list;
    }

    public List<MenuTree> selectMenuTree(Menu menu) {
        List<MenuTree> list = Collections.emptyList();
        List<Menu> menuList = this.selectList(menu);
        if (CollectionUtils.isEmpty(menuList)) {
            return list;
        }
        // 构建树
        list = buildTrees(menuList);
        if (StringUtils.equals(menu.getType(), Menu.TYPE_BUTTON)) {
            return list;
        }
        return (List<MenuTree>) TreeUtils.build(list);
    }

    private List<MenuTree> buildTrees(List<Menu> menus) {
        List<MenuTree> trees = new ArrayList<>();
        menus.forEach(menu -> {
            MenuTree tree = new MenuTree();
            tree.setId(menu.getMenuId().toString());
            tree.setParentId(menu.getParentId().toString());
            tree.setLabel(menu.getMenuName());
            tree.setComponent(menu.getComponent());
            tree.setIcon(menu.getIcon());
            tree.setOrderNum(menu.getOrderNum());
            tree.setPath(menu.getPath());
            tree.setType(menu.getType());
            tree.setPerms(menu.getPerms());
            trees.add(tree);
        });
        return trees;
    }

    /**
     * 查询列表
     * @param menu
     * @return
     */
    public List<Menu> selectList(Menu menu) {
        LambdaQueryWrapper<Menu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        String menuName = menu.getMenuName();
        if (StringUtils.isNotBlank(menuName)) {
            lambdaQueryWrapper.like(Menu::getMenuName, menuName);
        }
        lambdaQueryWrapper.orderByAsc(Menu::getOrderNum);
        return this.baseMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 增加menu
     * @param menu menu
     */
    public void addMenu(Menu menu) {
        menu.setCreateTime(LocalDateTime.now());
        setMenu(menu);
        this.save(menu);
    }

    private void setMenu(Menu menu) {
        Long parentId = menu.getParentId();
        if (parentId == null) {
            menu.setParentId(0L);
        } else {
            Long menuId = menu.getMenuId();
            if (menuId != null) {
                if (parentId.longValue() == menuId) {
                    menu.setParentId(0L);
                }
            }
        }
        if (Menu.TYPE_BUTTON.equals(menu.getType())) {
            menu.setPath(null);
            menu.setIcon(null);
            menu.setComponent(null);
            menu.setOrderNum(null);
        }
    }

    public void updateMenu(Menu menu) {
        Long menuId = menu.getMenuId();
        if (menuId == null) {
            throw new ParameterException(SystemStatus.MENU_ID_EMPTY);
        }
        menu.setModifyTime(LocalDateTime.now());
        setMenu(menu);
        this.baseMapper.updateById(menu);
    }

    @Transactional
    public void deleteMenuByIds(List<String> idList) {
        this.delete(idList);
    }

    private void delete(List<String> menuIds) {
        this.baseMapper.deleteBatchIds(menuIds);

        // 是否有子菜单
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Menu::getParentId, menuIds);
        List<Menu> menus = baseMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(menus)) {
            List<String> menuIdList = new ArrayList<>();
            menus.forEach(m -> menuIdList.add(String.valueOf(m.getMenuId())));
            // 递归删除
            this.delete(menuIdList);
        }
    }
}
